Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash when back-deploying concurrency to iOS 15.0/15.1-era OSs #65760

Conversation

DougGregor
Copy link
Member

@DougGregor DougGregor commented May 8, 2023

The introduction of the library providing back-deployment fixes for Swift 5.6 concurrency libraries (and older) introduced a concurrency crash in the following OS version ranges

  • macOS [12.0, 12.1)
  • iOS [15.0, 15.2)
  • tvOS [15.0, 15.2)
  • watchOS [8.0, 8.3)

Neither older nor newer versions of the listed OSs were affected.

The actual bug involved a miscommunication between the code in the library that back-deploys fixes (libswiftCompatibility56.a) and the concurrency library in the OS itself. Specifically, the OS versions at the end of the ranges above introduced voucher support into the concurrency runtime in the OS (an important feature for performance). The code in libswiftCompatibility56.a that back-ports concurrency fixes also included the voucher support, which provides a consistent state for those OS versions and anything newer.

OS versions that predate the introduction of concurrency in the OS are similarly unaffected, because the embedded
libswift_Concurrency.dylib matches that of Swift 5.6, which includes voucher support.

The OS versions in the affected range include a concurrency library in the OS that does not manage vouchers. The libswiftCompatibility56.a back-deployed fixes library has code that works on the same data structures but does manage vouchers, leading to crashes when (say) a job allocated by the OS version didn't set the "voucher" field, but the libswiftCompatibility56.a tried to free it, essentially a form of overrelease.

The fix is to teach the voucher-handling code in
libswiftCompatibility56.a to first check what version of the OS it is executing on. If it's in the affected range, all handling of vouchers is disables so it acts like the concurrency library in the OS. For both earlier OS versions and later OS versions the voucher-handler code executes unchanged. This entirely library is disabled when running on OS versions containing the Swift 5.7 concurrency library (or newer), so those don't need to pay for the extra check when dealing with vouchers.

Fixes rdar://108837762, rdar://108864311, rdar://108958765.

The introduction of the library providing back-deployment fixes for
Swift 5.6 concurrency libraries (and older) introduced a concurrency
crash in the following OS version ranges

  - macOS [12.0, 12.1)
  - iOS [15.0, 15.1)
  - tvOS [15.0, 15.1)
  - watchOS [8.0, 8.2)

Neither older nor newer versions of the listed OSs were affected.

The actual bug involved a miscommunication between the code in the
library that back-deploys fixes (`libswiftCompatibility56.a`) and the
concurrency library in the OS itself. Specifically, the OS versions at
the end of the ranges above introduced voucher support into the
concurrency runtime in the OS (an important feature for performance).
The code in `libswiftCompatibility56.a` that back-ports concurrency fixes
also included the voucher support, which provides a consistent state
for those OS versions and anything newer.

OS versions that predate the introduction of concurrency in the OS are
similarly unaffected, because the embedded
`libswift_Concurrency.dylib` matches that of Swift 5.6, which includes
voucher support.

The OS versions in the affected range include a concurrency library in
the OS that does not manage vouchers. The `libswiftCompatibility56.a`
back-deployed fixes library has code that works on the same data
structures but does manage vouchers, leading to crashes when (say) a
job allocated by the OS version didn't set the "voucher" field, but
the `libswiftCompatibility56.a` tried to free it, essentially a form of
overrelease.

The fix is to teach the voucher-handling code in
`libswiftCompatibility56.a` to first check what version of the OS it
is executing on. If it's in the affected range, all handling of
vouchers is disables so it acts like the concurrency library in the
OS. For both earlier OS versions and later OS versions the
voucher-handler code executes unchanged. This entirely library is
disabled when running on OS versions containing the Swift 5.7
concurrency library (or newer), so those don't need to pay for the
extra check when dealing with vouchers.

Fixes rdar://108837762, rdar://108864311, rdar://108958765.
@DougGregor DougGregor requested a review from a team as a code owner May 8, 2023 10:21
@DougGregor
Copy link
Member Author

@swift-ci please test

@ktoso ktoso added concurrency Feature: umbrella label for concurrency language features 🍒 release cherry pick Flag: Release branch cherry picks swift 5.8 labels May 8, 2023
@DougGregor
Copy link
Member Author

Spurious failure, yay

@DougGregor
Copy link
Member Author

@swift-ci please test macOS

The back-deployed concurrency library, which is used on OS versions
prior to the introduction of concurrency, has a Swift 5.6-era
concurrency library that supports vouchers.
@DougGregor
Copy link
Member Author

@swift-ci please test

`__builtin_available` requires linking compiler-rt, which
is not easier to do within the backward compatibility libraries.
Instead, use an API that's been in the standard library since before
Swift 5.0 for the version check.
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please build toolchain macOS

@dk-jlew
Copy link

dk-jlew commented May 8, 2023

@DougGregor is there anything to be aware of in terms of call patterns to change/avoid until this fix can be taken?

@DougGregor DougGregor merged commit 04106fb into apple:release/5.8 May 9, 2023
6 checks passed
@DougGregor DougGregor deleted the fix-back-deploy-dawn-of-concurrency-time-5.8 branch May 9, 2023 00:24
@aclima93
Copy link

@DougGregor is there anything to be aware of in terms of call patterns to change/avoid until this fix can be taken?

Personally I think (because the crash reports match those found by other users here) I've seen this cause intermittent crashes when using a Task, which triggers a withThrowingTaskGroup, which in turn uses a withCheckedThrowingContinuation to interface with a closure callback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
concurrency Feature: umbrella label for concurrency language features 🍒 release cherry pick Flag: Release branch cherry picks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants